#include "helper.h"
#include "reg.h"

extern uint32_t in_str;
extern char assembly[80];

/* decode I12-type instruction with unsigned immediate */
static void decode_ui12_type(uint32_t instr) {

    op_src1->type = OP_TYPE_REG;
    op_src1->reg = (instr >> 5) & 0x0000001F;
    op_src1->val = reg_w(op_src1->reg);

    op_src2->type = OP_TYPE_IMM;
    op_src2->simm = (int) ((instr >> 10) & 0x00000FFF) << 20 >> 20;

    op_dest->type = OP_TYPE_REG;
    op_dest->reg = instr & 0x0000001F;
}

make_helper(ld_b) {
    decode_ui12_type(in_str);
    uint32_t addr = (op_src1->val + op_src2->simm) & 0x7FFFFFFF;
    reg_w(op_dest->reg) = mem_read(addr,1);
    sprintf(assembly, "ld.b\t%s,\t%s,\t0x%03x", REG_NAME(op_dest->reg), REG_NAME(op_src1->reg), op_src2->simm);
    TRACE;
}

make_helper(ld_w) {
    decode_ui12_type(in_str);
    uint32_t addr = (op_src1->val + op_src2->simm) & 0x7FFFFFFF;
    reg_w(op_dest->reg) = mem_read(addr,4);
    sprintf(assembly, "ld.w\t%s,\t%s,\t0x%03x", REG_NAME(op_dest->reg), REG_NAME(op_src1->reg), op_src2->simm);
    TRACE;
}

make_helper(st_b) {
    decode_ui12_type(in_str);
    uint32_t addr = (op_src1->val + op_src2->simm) & 0x7FFFFFFF;
    int data = reg_w(op_dest->reg);
    mem_write(addr,1,data);
    sprintf(assembly, "st.b\t%s,\t%s,\t0x%03x", REG_NAME(op_dest->reg), REG_NAME(op_src1->reg), op_src2->simm);
}

make_helper(st_w) {
    decode_ui12_type(in_str);
    uint32_t addr = (op_src1->val + op_src2->simm) & 0x7FFFFFFF;
    int data = reg_w(op_dest->reg);
    mem_write(addr,4,data);
    sprintf(assembly, "st.w\t%s,\t%s,\t0x%03x", REG_NAME(op_dest->reg), REG_NAME(op_src1->reg), op_src2->simm);
}